;file: x86/arch/cpu/x86.asm
;autor: jiangxinpeng
;time: 2021.10.17
;copyrightL: (C) 2020-2050 by jiangxinpeng,All right are reserved.

[bits 32]
[section .text]

global ReadCR0
global ReadCR1
global ReadCR2
global ReadCR3
global WriteCR0
global WriteCR1
global WriteCR2
global WriteCR3
global X86Invlpg
global X86CPUID
global CPUhlt
global CPUNOP
global StoreGDTR
global LoadGDTR
global StoreEflag
global LoadEflag
global StoreIDTR
global LoadIDTR
global StoreLDTR
global LoadLDTR
global LoadTR 
global StoreTR
global LoadEflag
global StoreEflag
global DisInterrupt
global EnInterrupt
global _In16
global _In8
global _In32
global _Out32
global _Out16
global _Out8
global ReadMSR
global WriteMSR
global _RdTsc

ReadCR0: 
    xor eax,eax
    mov eax,cr0 
    ret 

ReadCR1:
    xor eax,eax
    mov eax,cr1
    ret 

ReadCR2:    
    xor eax,eax
    mov eax,cr2 
    ret 

ReadCR3:
    xor eax,eax 
    mov eax,cr3 
    ret 

WriteCR0:
    push eax
    mov eax,[esp+8]
    mov cr0,eax 
    pop eax
    ret 

WriteCR1:
    push eax
    mov eax,[esp+8]
    mov cr1,eax 
    pop eax
    ret 

WriteCR2:   
    push eax
    mov eax,[esp+8]
    mov cr2,eax 
    pop eax
    ret 

WriteCR3:
    push eax
    mov eax,[esp+8]
    mov cr3,eax 
    pop eax 
    ret 

;_In8(uint16_t port)
_In8:
    push edx
    xor eax,eax
    xor edx,edx 
    mov edx,[esp+8]
    in al,dx 
    pop edx 
    ret 

;__In8(uint16_t port)
_In16:
    push edx 
    xor eax,eax
    xor edx,edx  
    mov edx,[esp+8]
    in ax,dx 
    pop edx 
    ret 

;__In8(uint16_t port)
_In32:
    push edx 
    xor eax,eax
    xor edx,edx 
    mov edx,[esp+8]
    in eax,dx
    pop edx 
    ret 

;_Out8(uint16_t port,uint8_t data)
_Out8:
    push edx 
    push eax 
    xor eax,eax
    xor edx,edx
    mov edx,[esp+12]
    mov eax,[esp+16]
    out dx,al
    pop eax 
    pop edx
    ret 

;_Out16(uint16_t port,uint16_t data)
_Out16:
    push edx 
    push eax 
    xor eax,eax 
    xor edx,edx
    mov edx,[esp+12]
    mov eax,[esp+16]
    out dx,ax
    pop eax
    pop edx
    ret 

;_Out32(uint16_t port,uint32_t data)
_Out32:
    push edx
    push eax
    xor eax,eax 
    xor edx,edx
    mov edx,[esp+12]
    mov eax,[esp+16]
    out dx,eax
    pop eax
    pop edx 
    ret 

;void CPUhlt()
CPUhlt:
    cli 
    hlt
    ret 

;void X86CPUID(uint32_t fun,uint32_t a,uint32_t b,uint32_t c,uint32_t d)
X86CPUID:
    push eax 
    push ebx
    push ecx
    push edx 

    mov eax,[esp+20]
    cpuid 

    push ebx
    mov ebx,[esp+24]
    mov [ebx],eax
    pop ebx 
    mov eax,[esp+28]
    mov [eax],ebx
    mov eax,[esp+32]
    mov [eax],ecx
    mov eax,[esp+36]
    mov [eax],edx

    pop edx
    pop ecx
    pop ebx
    pop eax 
    ret 

EnInterrupt:
    sti 
    ret 

DisInterrupt:
    cli 
    ret 

;void StoreGDTR(uint32_t gdt)
StoreGDTR:
    push edx 
    mov edx,[esp+8]
    sgdt [edx]
    pop edx
    ret 

;void LoadGDTR(uint16_t limit,uint32_t base)
LoadGDTR:
    push edx
    mov dx,[esp+8]
    mov [esp+10],dx
    lgdt [esp+10]

    mov ax,0x10
    mov ds,ax
    mov es,ax
    mov gs,ax
    mov fs,ax 
    mov ss,ax
    jmp dword 0x08:.1
.1:
    pop edx
    ret 

;void StoreLDTR(uint64_t ldt)
StoreLDTR:
    push edx 
    mov edx,[esp+8]
    sldt [edx]
    pop edx
    ret

;void LoadLDTR(uint16_t limit,uint32_t limit)
LoadLDTR:
    push edx
    mov dx,[esp+8]
    mov [esp+10],dx
    lldt [esp+10]
    pop edx
    ret 

;void StoreIDTR(uint32_t idt)
StoreIDTR:
    push edx
    mov edx,[esp+8]
    sidt [edx]
    pop edx
    ret 

;void LoadIDTR(uint16_t limit,uint32_t idt)
LoadIDTR:
    push edx 
    mov dx,[esp+8]
    mov [esp+10],dx
    lidt [esp+10]
    pop edx
    ret 
    
LoadTR:
    push edx
    xor edx,edx
    mov dx,[esp+8]
    ltr dx
    pop edx
    ret 

StoreTR:
    push edx
    xor edx,edx
    mov dx,[esp+8]
    str edx
    pop edx
    ret 

LoadEflag:
    push eax 
    mov eax,[esp+8]
    push eax
    popf
    pop eax
    ret

StoreEflag:
    pushf
    pop eax
    ret 

CPUNOP:
    nop
    ret 

X86Invlpg:
    push edx
    mov edx,[esp+8]
    invlpg [edx]
    pop edx 
    ret 

;void ReadMSR(uint32_t id,uint32_t *eax,uint32_t *edx)
ReadMSR:
    push eax
    push ebx 
    push ecx 
    push edx 

    mov ecx,[esp+20]    ;id 
    rdmsr 
    mov ebx,[esp+24]    ;get eax
    mov [ebx],eax 
    mov ebx,[esp+28]    ;get edx
    mov [edx],edx   

    pop edx 
    pop ecx 
    pop ebx 
    pop eax 
    ret 

;void WriteMSR(uint32_t id,uint32_t eax,uint32_t edx)
WriteMSR:
    push eax 
    push ebx 
    push ecx 
    push edx 

    mov ecx,[esp+20] ;id 
    mov eax,[esp+24] ;eax
    mov edx,[esp+28] ;edx 
    wrmsr 

    pop edx 
    pop ecx 
    pop ebx 
    pop eax 
    ret 

_RdTsc:
   push eax 
   push edx
   rdtsc
   mov [esp+16],edx ;high
   mov [esp+12],eax ;low
   pop edx
   pop eax 
   ret